package model;

import dao.DaoException;
import dao.DaoFactory;
import dao.EmailDao;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.io.IOException;
import java.io.Serializable;
import java.sql.Timestamp;
import org.apache.commons.lang3.*;

/**
 * 
 * This class is Email model class
 * 
 * The email class represents an email object with its parameters 
 * @author Sukhjinder K. Narula (narula.sk@gmail.com)
 * @since May 2013
 * @version $Revision: 1.0 $
 */
public class Email implements Serializable{


	private static final long serialVersionUID = 1L;
	transient private EmailDao dao;
	transient private int id;
	private String to;
	private String from;
	private String subject;
	private String body;
	private boolean read;
	private Timestamp timestamp;
	transient private String pendingRecepients;
	

	/**
	 * Constructor
	 */
	public Email() {
		this.id = -1;
		this.dao = DaoFactory.getEmailDao();
		this.read = false;
	}

	/**
	 * Tells if there are any pending recepients in the email object
	 * @return
	 */
	public boolean hasNoMorePendingRecepients(){
		if (pendingRecepients.trim().isEmpty()){
			return true;
		}
		return false;
	}
	
	/**
	 * Removes a recepient from the pending recepients list
	 * 
	 * @param username
	 */
	synchronized public void removePendingRecepient(String username){
		
		System.out.println("Trying to remove " + username + " from : " + pendingRecepients) ;
		
		
		
		List<String> beforeList = Arrays.asList(this.pendingRecepients.toLowerCase().trim().split(","));
		List<String> afterList = new ArrayList<String>();
		
		
		Iterator<String> it = beforeList.iterator();
		while(it.hasNext()){
		    String r = it.next();
		    if (!r.isEmpty() && !r.trim().equalsIgnoreCase(username)){
		    	afterList.add(r);
		    }
		}
		if (afterList.size() == 0){
			pendingRecepients = "";
		} else {
			pendingRecepients = org.apache.commons.lang3.StringUtils.join(afterList, ",");
		}
		
		System.out.println("After removal, it becomes:  " + pendingRecepients + "\n\n");
		
	}
	
	/**
	 * Tells if a username is present in the pending recepients list of the email
	 * @param username
	 * @return
	 */
	public boolean hasPendingRecepient(String username){
		for(String recipient : Arrays.asList(this.pendingRecepients.split(","))){
			if (recipient.trim().equalsIgnoreCase(username.trim())){
				return true;
			}
		}
		return false;
	}
	
	
	/**
	 * Gets the pendingRecepients of the email
	 * @return
	 */
	public String getPendingRecepients() {
		return pendingRecepients;
	}

	/**
	 * sets the pendingRecepients of the email
	 * @param pendingRecepients
	 */
	public void setPendingRecepients(String pendingRecepients) {
		this.pendingRecepients = pendingRecepients;
	}


	/**
	 * Gets the email id
	
	 * @return the id */
	public int getId() {
		return id;
	}


	/**
	 * Gets the to field
	
	 * @return the to */
	public String getTo() {
		return to;
	}


	/**
	 * Gets the from field
	
	 * @return the from */
	public String getFrom() {
		return from;
	}


	/**
	 * Gets the subject field
	
	 * @return the subject */
	public String getSubject() {
		return subject;
	}


	/**
	 * Gets the body field
	
	 * @return the body */
	public String getBody() {
		return body;
	}


	/**
	 * Gets the read field
	
	 * @return the read */
	public boolean isRead() {
		return read;
	}


	/**
	 * Gets the timestamp field
	
	 * @return the timestamp */
	public Timestamp getTimestamp() {
		return timestamp;
	}




	/**
	 * Sets the email id
	
	 * @param id int
	 */
	public void setId(int id) {
		this.id = id;
	}


	/**
	 * Sets the email to field
	
	 * @param to String
	 */
	public void setTo(String to) {
		this.to = to;
	}


	/**
	 * Sets the email from field
	
	 * @param from String
	 */
	public void setFrom(String from) {
		this.from = from;
	}


	/**
	 * Sets the email subject field
	
	 * @param subject String
	 */
	public void setSubject(String subject) {
		this.subject = subject;
	}


	/**
	 * Sets the email body field
	
	 * @param body String
	 */
	public void setBody(String body) {
		this.body = body;
	}


	/**
	 * Sets the email read field
	
	 * @param read boolean
	 */
	public void setRead(boolean read) {
		this.read = read;
	}


	/**
	 * Sets the email timestamp field
	
	 * @param timestamp Timestamp
	 */
	public void setTimestamp(Timestamp timestamp) {
		this.timestamp = timestamp;
	}


	/**
	 * 
	 * @throws ModelException
	 */
	public void save() throws ModelException{
		
		if (id == -1){
			try {
				id = dao.create(getTransferObject());
			} catch (DaoException e) {
				throw new ModelException(e.getMessage());
			}
		} else {
			try {
				dao.update(getTransferObject());
			} catch (DaoException e) {
				throw new ModelException(e.getMessage());
			}
		}
	}

	
	/**
	 * Creates string hash map of properties
	
	 * @return a String representation of the properties. */
	public HashMap<String, String> getTransferObject(){
		
		HashMap<String, String> toReturn = new HashMap<String, String>();
		toReturn.put("Id", String.valueOf(id));
		toReturn.put("ToEmail", to);
		toReturn.put("FromEmail", from);
		toReturn.put("Subject", subject);
		toReturn.put("Body", body);
		toReturn.put("Read", String.valueOf(read));
		toReturn.put("Ts", String.valueOf(timestamp));
		toReturn.put("PendingRecepients", pendingRecepients);
		return toReturn;
	}
	
	/**
	 * Returns a readable format for the email (for testing purposes)
	 */
	public String toString(){
		
		String toReturn = "\n\n------------ email start ----------------\n";
		toReturn += "id: " + id + "\n" +
				"to: " + to + "\n" + 
				"from: " + from + "\n" + 
				"subject: " + subject + "\n" +
				"body" + body +  "\n" + 
				"read: " + read +  "\n" + 
				"ts" + timestamp +  "\n" + 
				"pendingRecepients: " + pendingRecepients +  "\n" +
				"--------- email end ----------------------";
		
		return toReturn;
	}

	/**
	 * Deletes the email from the database
	
	 * @throws DaoException  */
	public void delete() throws DaoException {
		dao.delete(id);
	}
	
	/**
	 * Checks if the email fields to, from, body and subject contain a predefined text and returns a boolean value indicating
	 * the result.
	
	
	 * @param text String
	 * @return boolean value of a found or not found result. */
	public boolean match(String text){
		
		String target=this.getTo()+this.getFrom()+this.getBody()+this.getSubject();
		
		if(target.toLowerCase().contains(text.toLowerCase()))
		return true;
		else
			return false;
	}
	
	
	/**
	 * Tells if this email has a given user in the recepient list
	 * @param username
	 * @return
	 */
	public boolean hasRecipient(String username){
		for(String recipient : Arrays.asList(this.to.split(","))){
			if (recipient.trim().equalsIgnoreCase(username.trim())){
				return true;
			}
		}
		return false;
	}
	
//	/**
//	 * Overriding the write object to take care of transient fields
//	 * 
//	 * @param is
//	 * @throws IOException
//	 * @throws ClassNotFoundException
//	 */
//	private void writeObject(java.io.ObjectOutputStream os)
//            throws IOException, ClassNotFoundException {
//		os.defaultWriteObject();
//        id = -1;
//        dao = null;
//    }
	
	
	/**
	 * Overriding the read object to take care of transient fields
	 * 
	 * @param is
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	private void readObject(java.io.ObjectInputStream is)
            throws IOException, ClassNotFoundException {
		is.defaultReadObject();
        id = -1;
        dao = DaoFactory.getEmailDao();
        pendingRecepients = to;
    }

	/**
	 * Returns an array list of pending recipients
	 * 
	 * @return Array list of pending recipients
	 */
	public ArrayList<String> getPendingRecepientsList() {
		
		ArrayList<String> toReturn = new ArrayList<String>();
		for(String recipient : Arrays.asList(pendingRecepients.trim().split(","))){
			if ( !recipient.isEmpty() ){
				toReturn.add(recipient);
			}
		}
		return toReturn;
	}
	
	
	
}
